<template>
  <div>
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>文章列表</span>
      </div>
      <div class="artList-box">
        <div>
          <el-form
            :inline="true"
            :model="formInline"
            size="mini"
            class="demo-form-inline"
            ref="searchForm"
          >
            <el-form-item label="文章分类">
              <el-select v-model="formInline.cate_id" placeholder="请选择分类">
                <el-option
                  v-for="item in cateList"
                  :label="item.cate_name"
                  :value="item.id"
                  :key="item.id"
                ></el-option>
              </el-select>
            </el-form-item>

            <el-form-item label="发布状态">
              <el-select v-model="formInline.state" placeholder="请选择状态">
                <el-option label="已发布" value="已发布"></el-option>
                <el-option label="草稿" value="草稿"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="filterFn">筛选</el-button>
              <el-button type="info" @click="resetFn">重置</el-button>
            </el-form-item>
          </el-form>
        </div>
        <div>
          <el-button type="primary" size="mini" @click="onFrom"
            >发布文章</el-button
          >
        </div>
        <!-- 发表文章的 Dialog 对话框 -->
        <el-dialog
          title="发表文章"
          :visible.sync="pubDialogVisible"
          fullscreen
          :before-close="handleClose"
        >
          <el-form
            ref="form"
            :model="form"
            :rules="pubFormRules"
            label-width="100px"
          >
            <el-form-item label="文章标题" prop="title">
              <el-input v-model="form.title"></el-input>
            </el-form-item>
            <el-form-item label="文章分类" prop="cate_id">
              <el-select
                class="select-box"
                v-model="form.cate_id"
                placeholder="请选择分类"
              >
                <el-option
                  v-for="item in cateList"
                  :label="item.cate_name"
                  :value="item.id"
                  :key="item.id"
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- 富文本 -->
            <el-form-item label="文章内容" prop="content" class="text-box">
              <quill-editor
                v-model="form.content"
                @blur="onEditorChange($event)"
              ></quill-editor>
            </el-form-item>
            <!-- 封面头像 -->
            <el-form-item label="封面头像" prop="cover_img">
              <img
                src="@/assets/images/cover.jpg"
                alt=""
                class="img-cover"
                v-if="!form.cover_img"
                ref="imgRef"
              />
              <img :src="avatar" alt="" class="img-cover" v-else />
              <input
                type="file"
                style="display: none"
                ref="iptFileRef"
                @change="onFileSel"
              />
              <el-button type="text" @click="selCover"> + 选择封面</el-button>
            </el-form-item>

            <el-form-item>
              <el-button type="primary" @click="onPutOut('已发布')"
                >发布</el-button
              >
              <el-button type="info" @click="onDraft('草稿')"
                >存为草稿</el-button
              >
            </el-form-item>
          </el-form>
        </el-dialog>
      </div>
      <!-- 文章表格区域 -->
      <el-table :data="artList" style="width: 100%" border stripe>
        <el-table-column label="文章标题" prop="title">
          <template v-slot="{ row }">
            <el-link type="primary" @click="showDetailFn(row.id)">{{
              row.title
            }}</el-link>
          </template>
        </el-table-column>
        <el-table-column label="分类" prop="cate_name"></el-table-column>
        <el-table-column label="发表时间" prop="pub_date">
          <template v-slot="scope">
            <span>{{ $formatDate(scope.row.pub_date) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="状态" prop="state"></el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ row }"
            ><el-button type="danger" size="mini" @click="removeListFn(row.id)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <!-- 标题的通知框 -->
      <el-dialog
        title="文章预览"
        :visible.sync="titleInfrom"
        width="80%"
        class="preview-box"
      >
        <!-- 文章标题和部分信息内容 -->
        <div class="title-box">
          <h5>{{ ArtInfo.title }}</h5>
          <span>作者:{{ ArtInfo.username || ArtInfo.nickname }}</span>
          <span>发布时间:{{ $formatDate(ArtInfo.pub_date) }}</span>
          <span>所属分类:{{ ArtInfo.cate_nam }}</span>
          <span>状态:{{ ArtInfo.state }}</span>
        </div>

        <div class="xiahuaxian"></div>
        <!-- 文章封面 -->
        <div>
          文章封面:<a
            :href="'http://big-event-vue-api-t.itheima.net' + ArtInfo.cover_img"
            >{{ baseURL + ArtInfo.cover_img }}</a
          >
        </div>
        <!-- 文章内容 -->
        <!-- 文章的详情 -->
        <div v-html="ArtInfo.content" class="detail-box"></div>
      </el-dialog>

      <!-- 分页区域 -->
      <!-- size-change:sizes发生改变的时候触发返回一个sizes的值
           current-change：页面发生改变时触发返回一个页数的实参
       -->
      <el-pagination
        @size-change="handleSizeChangeFn"
        @current-change="handleCurrentChangeFn"
        :current-page.sync="formInline.pagenum"
        :page-sizes="[2, 3, 5, 10]"
        :page-size.sync="formInline.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      >
      </el-pagination>
    </el-card>
  </div>
</template>

<script>
import {
  getArtCateApi,
  PutOutArtCateApi,
  getArtListApi,
  getArtdetailsApi,
  removeArtListApi
} from '@/api/index'
import { baseURL } from '@/utils/request'
export default {
  data () {
    return {
      // 基地址
      baseURL: baseURL,
      avatar: '',
      // 文章分类
      cateList: [],
      // 现有文章的总数
      total: 0,
      // 文章列表
      artList: [],
      formInline: {
        pagenum: 1,
        pagesize: 2,
        cate_id: '',
        state: ''
      },
      form: {
        title: '',
        cate_id: '',
        // 富文本
        content: '',
        cover_img: null,
        state: ''
      },
      pubFormRules: {
        // 表单的验证规则对象
        title: [
          { required: true, message: '请输入文章标题', trigger: 'blur' },
          {
            min: 1,
            max: 30,
            message: '文章标题的长度为1-30个字符',
            trigger: 'blur'
          }
        ],
        // 下拉菜单不能失去焦点，所以不能用blur
        cate_id: [
          { required: true, message: '请选择文章分类', trigger: 'change' }
        ],
        // 应为这个是富文本编辑器，他不是el提供的表单标签，所以在进行blur时，不会进行校验
        content: [
          { required: true, message: '请输入文章内容', trigger: 'change' }
        ],
        cover_img: [
          { required: true, message: '请选择文章内容', trigger: 'change' }
        ]
      },
      // 文章信息
      ArtInfo: {},
      pubDialogVisible: false,
      // 标题的通知框
      titleInfrom: false
    }
  },
  methods: {
    // 发布按钮
    onPutOut (str) {
      this.form.state = str
      this.$refs.form.validate(async (value) => {
        if (value) {
          const fd = new FormData()
          fd.append('title', this.form.title)
          fd.append('cate_id', this.form.cate_id)
          fd.append('content', this.form.content)
          fd.append('cover_img', this.form.cover_img)
          fd.append('state', this.form.state)

          const { data: res } = await PutOutArtCateApi(fd)
          if (res.code !== 0) {
            return this.$message.error(res.message)
          } else {
            this.$message.success(res.message)
          }
        } else {
          this.$message.warning('表单验证失败')
          return false
        }
      })
    },
    // 草稿按钮
    onDraft (str) {
      this.form.state = str
      this.$refs.form.validate(async (value) => {
        if (value) {
          const fd = new FormData()
          fd.append('title', this.form.title)
          fd.append('cate_id', this.form.cate_id)
          fd.append('content', this.form.content)
          fd.append('cover_img', this.form.cover_img)
          fd.append('state', this.form.state)

          const { data: res } = await PutOutArtCateApi(fd)
          if (res.code !== 0) {
            return this.$message.error(res.message)
          } else {
            this.$message.success('已存入草稿')
          }
        } else {
          return false
        }
      })
    },
    // 对话框的弹出
    onFrom () {
      this.pubDialogVisible = true
    },
    // 对话框关闭是的提示
    // done ：调用就会关闭对话框
    async handleClose (done) {
      // 询问用户是否确认关闭对话框
      const confirmResult = await this.$confirm(
        '此操作将导致文章信息丢失, 是否继续?',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).catch((err) => err)
      console.log(confirmResult)
      if (confirmResult === 'confirm') {
        this.$refs.form.resetFields()
      }
      // 取消了关闭-阻止住, 什么都不干
      if (confirmResult === 'cancel') return
      // 确认关闭
      done()
    },
    // 获取所有分类
    async getArtCateList () {
      const { data: res } = await getArtCateApi()
      this.cateList = res.data
    },
    // 选择封面的点击事件
    selCover () {
      this.$refs.iptFileRef.click()
    },
    // 用户选择的文件
    onFileSel (e) {
      const files = e.target.files
      if (files.length === 0) {
        this.form.cover_img = null
      } else {
        this.form.cover_img = files[0]
        // 给这个部分表单标签进行一个校验
        this.$refs.form.validateField('cover_img')
        // 使文件能预览
        this.avatar = URL.createObjectURL(files[0])
      }
    },
    // 给富文本编辑器添加change事件
    onEditorChange () {
      // 给这个部分表单标签进行一个校验
      this.$refs.form.validateField('content')
    },
    // 获取所有文章列表
    async getArtListFn () {
      const { data: res } = await getArtListApi(this.formInline)
      if (res.code !== 0) {
        return this.$message.error(res.message)
      } else {
        this.artList = res.data
        this.total = res.total
      }
    },
    // 每页条数改变时
    handleSizeChangeFn (sizes) {
      this.formInline.pagesize = sizes
      this.formInline.pagenum = 1
      this.getArtListFn()
    },
    // 当前页码改变时触发
    handleCurrentChangeFn (nowPage) {
      this.formInline.pagenum = nowPage
      this.getArtListFn()
    },
    // 偶发性bug:首先如果总数有10条，我选择5条每页，那么会有分为两页。然后我点击第二页，在选择10页一条，
    // 那么会发送pagenum=2$sizes=10的请求参数，那么会返回一个空数组。之后页码发生改变触发handleCurrentChangeFn函数。
    // 就会发送pagenum=1$sizes=10的请求参数，那么会返回一个正常的数组。
    // 但是如果pagenum=2$sizes=10的请求参数的响应时间太慢，慢于pagenum=1$sizes=10的请求参数的响应，那么页面就会返回一个空数组。
    // 导致页面没有数据。
    // 解决: 每页条数改变时，this.formInline.pagenum = 1
    // 筛选按钮
    filterFn () {
      this.formInline.pagesize = 2
      this.formInline.pagenum = 1
      this.getArtListFn()
    },
    // 重置
    resetFn () {
      this.formInline.pagesize = 2
      this.formInline.pagenum = 1
      this.formInline.cate_id = ''
      this.formInline.state = ''
      this.getArtListFn()
    },
    // 标题的点击函数
    async showDetailFn (id) {
      this.titleInfrom = true
      const { data: res } = await getArtdetailsApi(id)
      this.ArtInfo = res.data
    },
    // 删除文章分类
    async removeListFn (id) {
      const { data: res } = await removeArtListApi(id)
      if (res.code !== 0) {
        return this.$message.error(res.message)
      } else {
        // bug描述：如果在最后一页删除最后一个数据源，那么列表会没有数据
        // 原因：如果点击删除触发获取列表的函数，而里面的参数没有改变，他还是发送最后一页的参数
        // pagenum=最后一页的页码$sizes=(没页多少个数据),但是后台已经没有最后一页的列表了，所有会响应一个空的数组
        // 解决方法：在获取列表的函数前面使this.formInline.pagenum--，那么参数发生改变，后台就能获取到删除后最后一页的数据了
        // 数组里只保存当前也的数据，别答页需要传送参给后台管理
        if (this.artList.length === 1) {
          // 判断页码不能小于1
          if (this.formInline.pagenum > 1) {
            this.formInline.pagenum--
          }
        }
        this.getArtListFn()
        this.$message.success(res.message)
      }
    }
  },
  created () {
    // 文章分类
    this.getArtCateList()
    // 文章列表
    this.getArtListFn()
  }
}
</script>

<style lang="less" scoped>
.artList-box {
  display: flex;
  justify-content: space-between;
}
.select-box {
  width: 100%;
}
// // 设置富文本编辑器的默认最小高度 // ::v-deep作用: 穿透选择,
// 正常style上加了scope的话, 会给.ql-editor[data-v-hash]属性,
// 只能选择当前页面标签或者组件的根标签 //
// 如果想要选择组件内的标签(那些标签没有data-v-hash值)所以正常选择选不中,
// 加了::v-deep空格前置的话, 选择器就会变成如下形式 // [data-v-hash] .ql-editor
// 这样就能选中组件内的标签的class类名了
::v-deep.ql-editor {
  min-height: 300px;
}
.text-box {
  min-height: 300px;
  ::v-deep .ql-editor {
    min-height: 300px;
  }
}
.img-cover {
  display: block;
  width: 400px;
  height: 280px;
  object-fit: cover;
}
.el-pagination {
  padding-top: 18px;
  text-align: center;
}
/deep/ .preview-box {
  .el-dialog__body {
    padding-top: 0;
    h5 {
      text-align: center;
      font-size: 24px;
      color: #000;
      margin: 0 0 10px 0;
    }
    .title-box {
      span {
        display: inline-block;
        padding-right: 5px;
        font-size: 12px;
      }
    }
  }
  .xiahuaxian {
    border-bottom: 1px solid #dcdfe6;
    margin-top: 14px;
    margin-bottom: 24px;
  }
}
</style>
